﻿using System;
using System.Linq;
using System.Text;

namespace ch10.binary.type
{
    public struct FuncType
    {
        public byte Tag;
        public ValType[] ParamTypes;
        public ValType[] ResultTypes;

        public override int GetHashCode()
        {
            return Tag.GetHashCode() + ParamTypes?.GetHashCode() ?? 0 + ResultTypes?.GetHashCode() ?? 0;
        }

        public override bool Equals(object obj)
        {
            if (obj is not FuncType ft2) return false;
            //return reflect.DeepEqual(ft, ft2)
            if ((ParamTypes?.Length ?? 0) != (ft2.ParamTypes?.Length ?? 0))
            {
                return false;
            }

            if ((ResultTypes?.Length ?? 0) != (ft2.ResultTypes?.Length ?? 0))
            {
                return false;
            }

            ParamTypes ??= Array.Empty<ValType>();
            ResultTypes ??= Array.Empty<ValType>();

            return ParamTypes.SequenceEqual(ParamTypes);
        }

        internal string GetSignature()
        {
            var sb = new StringBuilder();
            sb.Append('(');
            for (var i = 0; ParamTypes != null && i < ParamTypes.Length; i++)
            {
                var vt = ParamTypes[i];
                if (i > 0)
                {
                    sb.Append(",");
                }

                sb.Append(Types.ValTypeToStr(vt));
            }

            sb.Append(")->(");
            for (var i = 0; ResultTypes != null && i < ResultTypes.Length; i++)
            {
                var vt = ResultTypes[i];
                if (i > 0)
                {
                    sb.Append(',');
                }

                sb.Append(Types.ValTypeToStr(vt));
            }

            sb.Append(')');
            return sb.ToString();
        }

        public override string ToString()
        {
            return GetSignature();
        }

        public static bool operator ==(FuncType left, FuncType right)
        {
            return left.Equals(right);
        }

        public static bool operator !=(FuncType left, FuncType right)
        {
            return !(left == right);
        }
    }
}